<?php
//支付
/*// 加载基础 adapay 基础类
// SDK 初始化文件加载
include_once  __ROOT__. "/SDK/AdapaySdk/init.php";
// 在文件中设置 DEBUG 为 true 时， 则可以打印日志到指定的日志目录下 LOG_DIR
include_once  __ROOT__. "/app/config/pay/pay.php";*/

use app\config\Db;
use Core\Result\Result;
use Core\Utils\Utils;
use GuzzleHttp\Client;
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use Core\Common\Common;

function orderPay($data)
{
    $order_id = $data['order_id'];//订单ID
    //$coupon_id = $data['coupon_id'];//优惠券ID
    $payType = $data['payType'];//支付方式//cloudPay//wechatPay//birthPay//assistPay
    $trade_password = $data['trade_password'];//支付密码，除了微信支付必验证
    $user_id = Common::getUser_id($data);
    $db = new Db("host");
    $userInfo  = $db->find("select ui.`user_id`,ui.`openid`,uei.`trade_password` from `user_info` as ui inner join `user_extra_info` as uei on ui.user_id = uei.user_id where ui.`user_id`=$user_id");
    if(empty($userInfo)){
        Result::error("账户失效，请重新登录");
    }
    if($payType != "wechatPay" && !empty($trade_password)){
        if(empty($userInfo["trade_password"])){
            Result::error("您还未设置支付密码，请先设置！");
        }
        $userInfo['trade_password'] = Common::passwordTh($userInfo['trade_password']);
        $generalVerify = Common::config('config')['generalVerify']['password'];
        if ($trade_password != $generalVerify && !password_verify($trade_password, $userInfo['trade_password'])){
            Result::error("支付密码错误");
        }
    }
    $orderInfo = $db->find("select `order_id`,`order_no`,`shop_id`,`parent_order_id`,`is_parent`,`goods_id`,`sku_id`,`order_number`,`order_price`,`order_total_price`,`shipping_fee`,`pay_status`,`order_state`,`order_type` from `ysmz_shop_goods_order` where `order_id`=$order_id and `user_id`=$user_id");
    if($orderInfo["order_state"] == 4) Result::error("订单已取消");
    if($orderInfo["order_total_price"] <= 0 )   Result::error("订单异常，请重新下单购买");
    if($orderInfo["pay_status"] != 1 || $orderInfo["order_state"] != 0 )  Result::error("订单已支付");
    if($orderInfo["is_parent"] == 1){
        $parent_order_id = $orderInfo["order_id"];
        $childOrderInfo = $db->query("select `order_id`,`order_no`,`shop_id`,`parent_order_id`,`is_parent`,`goods_id`,`sku_id`,`order_number`,`order_price`,`order_total_price`,`shipping_fee`,`pay_status`,`order_state`,`order_type` from `ysmz_shop_goods_order` where `parent_order_id`='$parent_order_id' and `user_id`='$user_id'");
        foreach ($childOrderInfo as $k=>$v){
            $childOrderGoodsInfo = $db->find("select gos.*,g.unreal_sales_volume,g.goods_type,g.is_top,g.is_adopt,g.is_task,g.shop_id,g.shipping_method,g.free_shipping,g.goods_type,g.fixed_shipping_fee,g.section_id from ysmz_shop_goods_sku as gos inner join ysmz_shop_goods as g on gos.goods_id=g.goods_id where gos.sku_id=$v[sku_id] limit 1");
            $orderInfo["goods_name"] = $childOrderGoodsName = $childOrderGoodsInfo["sku_name"];
            if ($childOrderGoodsInfo['is_top'] == 0 || $childOrderGoodsInfo['is_adopt'] == 0) Result::error($childOrderGoodsName."商品已下架");
            if ($childOrderGoodsInfo['sku_stock'] - $v["order_number"] < 0) Result::error($childOrderGoodsName."库存不足");
            $shopInfo = $db->find("select `status`,`shop_title` from `ysmz_shop` where `shop_id`=$v[shop_id]");
            if($shopInfo["status"] != 1){
                $shop_title = $shopInfo["shop_title"];
                Result::error($shop_title."店铺已停运或关闭");
            }
            if(!isMerchantPay($childOrderGoodsInfo["section_id"],$payType)){
                Result::error("商品不支持当前支付方式");
            }
        }
    }else{
        $goodsInfo = $db->find("select gos.*,g.unreal_sales_volume,g.goods_type,g.is_top,g.is_adopt,g.is_task,g.shop_id,g.shipping_method,g.free_shipping,g.goods_type,g.fixed_shipping_fee,g.section_id from ysmz_shop_goods_sku as gos inner join ysmz_shop_goods as g on gos.goods_id=g.goods_id where gos.sku_id=$orderInfo[sku_id] limit 1");
        if ($goodsInfo['is_top'] == 0 || $goodsInfo['is_adopt'] == 0) Result::error("商品已下架");
        if ($goodsInfo['sku_stock'] - $orderInfo["order_number"] < 0) Result::error("库存不足");
        $shopInfo = $db->find("select `status` from `ysmz_shop` where `shop_id`=$orderInfo[shop_id]");
        if($shopInfo["status"] != 1){
            Result::error("店铺已停运或关闭");
        }
        if(!isMerchantPay($goodsInfo["section_id"],$payType)){
            Result::error("商品不支持当前支付方式");
        }
        $orderInfo["goods_name"] = $goodsInfo["sku_name"];
    }
    $goods_price = $orderInfo["order_total_price"];
    /*if(!empty($coupon_id)){
        $couponInfo = $db->find("select id,uc.`coupon_id`,`coupon_money`,`min_order_amount`,`coupon_discount`,`coupon_type`,`reduce_type`,`send_range`,`send_range_data` from `user_coupon` as uc inner join `ysmz_coupon` as yc on uc.coupon_id = yc.coupon_id where uc.`id`=$coupon_id and uc.`user_id`=$user_id and uc.`order_id` = 0 and uc.start_date < $time and uc.end_date >$time");
        if($orderInfo["order_total_price"] < $couponInfo["min_order_amount"]){
            Result::error("请选择正确使用优惠券");
        }
        $json_decode = json_decode($couponInfo["send_range_data"]);
        switch ($couponInfo["send_range"]){
            case 3:
                if(!in_array($orderInfo["goods_id"], $json_decode)){
                    Result::error("请选择正确使用优惠券");
                }
                break;
            case 4:
                if(in_array($orderInfo["goods_id"], $json_decode)){
                    Result::error("请选择正确使用优惠券");
                }
                break;
        }
        switch ($couponInfo["coupon_type"]){
            case 1:$goods_price = $goods_price - $couponInfo["coupon_money"];break;
            case 2:$goods_price = $goods_price * ($couponInfo["coupon_discount"]/10);break;
        }
        if($goods_price > $orderInfo["order_total_price"] || $goods_price < 0){
            Result::error("优惠券异常，请勿使用");
        }
        $orderInfo["coupon_id"] = $couponInfo["id"];
        $orderInfo["order_coupon_price"] = $orderInfo["order_total_price"] - $goods_price;
    }*/
    $orderInfo["order_total_price"] = $orderInfo["order_pay_price"] = $goods_price + $orderInfo["shipping_fee"];
    $orderInfo["user_id"] = $user_id;
    $orderInfo["openid"] = $userInfo["openid"];
    $orderInfo["order_coupon_price"] = 0;
    switch ($payType) {
        case 'cloudPay'://余额支付
            $orderInfo["payment_type"] = 1;
            cloudPay($orderInfo);
            break;
        case 'wechatPay'://微信支付
            $orderInfo["payment_type"] = 2;
            wechatPay($orderInfo);
            break;
        case 'birthPay'://生日豆
            $orderInfo["payment_type"] = 4;
            cloudPay($orderInfo);
            break;
        case 'assistPay'://帮扶豆
            $orderInfo["payment_type"] = 5;
            cloudPay($orderInfo);
            break;
        default:Result::error("请选择支付方式");
    }
    Result::success();
}
/**
 * 云豆支付、生日豆支付、帮扶豆支付
 * @param $data
 * @return void
 */
function cloudPay($data)
{
    $db = new Db("host");
    $user_id = $data["user_id"];
    $order_total_price = $data["order_pay_price"];
    $userInfo = $db->find("select `cloud_bean`,`birth_bean`,`assist_bean` from `user_info` where `user_id`=$user_id");
    switch ($data["payment_type"]) {
        case 1:
            $data["cloud_bean"] = $userInfo["cloud_bean"];
            if($userInfo["cloud_bean"] < 0){
                Result::error("用户余额异常，请联系管理员");
            }
            if($userInfo["cloud_bean"] < $order_total_price){
                //Result::error("用户余额不足");
                $data["order_pay_price"] = $order_total_price - $userInfo["cloud_bean"];
                $data["payment_type"] = 3;
                wechatPay($data);//用户余额不足拉起微信支付
            }
            $data["data_src"] = 1;
            break;
        case 4:
            $data["birth_bean"] = $userInfo["birth_bean"];
            if($userInfo["birth_bean"] < 0){
                Result::error("用户余额异常，请联系管理员");
            }
            if($userInfo["birth_bean"] < $order_total_price){
                //Result::error("用户生日豆不足");
                $data["order_pay_price"] = $order_total_price - $userInfo["birth_bean"];
                $data["payment_type"] = 6;
                wechatPay($data);//用户余额不足拉起微信支付
            }
            $data["data_src"] = 3;
            break;
        case 5:
            $data["assist_bean"] = $userInfo["assist_bean"];
            if($userInfo["assist_bean"] < 0){
                Result::error("用户余额异常，请联系管理员");
            }
            if($userInfo["assist_bean"] < $order_total_price){
                //Result::error("用户帮扶豆不足");
                $data["order_pay_price"] = $order_total_price - $userInfo["assist_bean"];
                $data["payment_type"] = 7;
                wechatPay($data);//用户余额不足拉起微信支付
            }
            $data["data_src"] = 4;
            break;
    }

    $data["data_id"] = $data["order_no"];
    $data["data_remarks"] = "商品购买";
    $db->startTrans();
    try {
        userOperationCloud($db,$data);//更新用户余额
        orderSettlement($db,$data);//修改订单更新店铺余额
        if(!empty($data["coupon_id"])){
            couponSettlement($db,$data);
        }
        $db->commit();
    } catch (\Exception $e) {
        $db->rollback();
        Result::error($e->getMessage());
    }
    $messagesData["type"] = 2;
    $messagesData["sid"] = $data["shop_id"];
    $messagesData["msg_type"] = 2;
    $messagesData["msg"] = "用户下单";
    $messagesData["trade_no"] = $data["order_no"];
    pushCrmMessages($messagesData);
    Result::success("ok");
}
/**
 * 更新用户余额
 * */
function userOperationCloud($db,$data)
{
    $order_total_price = $data["order_total_price"];
    $user_id = $data["user_id"];
    $data_src =  $data["data_src"];//1云豆3生日豆4帮扶豆
    $data_id =  $data["data_id"];
    $data_remarks =  $data["data_remarks"];
    switch ($data_src) {
        case 1:
            $bean = $data["cloud_bean"];
            $setJoin = "`cloud_bean`=`cloud_bean` - $order_total_price";
            $whereJoin = "and `cloud_bean` = $bean";
            break;
        case 3:
            $bean = $data["birth_bean"];
            $setJoin = "`birth_bean`=`birth_bean` - $order_total_price";
            $whereJoin = "and `birth_bean` = $bean";
            break;
        case 4:
            $bean = $data["assist_bean"];
            $setJoin = "`assist_bean`=`assist_bean` - $order_total_price";
            $whereJoin = "and `assist_bean` = $bean";
            break;
    }
    $upUserSql = "update `user_info` set $setJoin where `user_id`=$user_id $whereJoin";
    $addOrderSql = "insert into `user_balance_detail`(user_id,balance,data_src,data_id,data_remarks,update_type,new_balance) values ($user_id,$order_total_price,$data_src,'$data_id','$data_remarks',2,$bean-$order_total_price)";
    if (!$db->save($upUserSql)) Common::exception("用户余额更新失败");
    if (!$db->save($addOrderSql)) Common::exception("用户流水更新失败");
}
/**
 * 优惠券使用
 * @param $data
 * @return void
 */
function couponSettlement($db, $data)
{
    $id = $data["coupon_id"];
    $order_id = $data["order_id"];
    $user_id = $data["user_id"];
    $time = time();
    $datetime = date('Y-m-d H:i:s', $time);
    $upCouponSql = "update `user_coupon` set `used_time`='$datetime',`order_id`=$order_id where `id`=$id and `user_id` = $user_id";
    if (!$db->save($upCouponSql)) Common::exception("优惠券更新失败");
}
/**
 * 订单更新、修改库存、店铺结算
 * @param $data
 * @return void
 */
function orderSettlement($db, $data)
{
    $order_pay_price = $shengyu = $data["order_pay_price"];//实际总支付
    $order_coupon_price = $data["order_coupon_price"];
    $payment_type = $data["payment_type"];
    $order_id = $data["order_id"];
    $user_id = $data["user_id"];
    $pay_status = 2;
    $order_state = 1;
    $datetime = date('Y-m-d H:i:s', time());
    $orderJoin = ",pay_time = '$datetime'";
    if($data["is_parent"] == 1){
        $queryChildOrder = $db->query("select `order_id`,`order_no`,`order_number`,`order_type`,`sku_id`,`shop_id`,`order_total_price`,`shipping_fee`,`order_fees`,`order_coupon_price`,`order_discount_price` from `ysmz_shop_goods_order` where `parent_order_id` = $order_id FOR UPDATE");
        foreach ($queryChildOrder as $key=>$value){
            if($shengyu < 0) $shengyu =0;
            $type = 2;
            $remarks = "商品出售";
            $data_id = $value["order_no"];
            $shopInfo = $db->find("select `shop_id`,`status`,`shop_money`,`frozen_money` from `ysmz_shop` where `shop_id`=$value[shop_id]");
            $shop_money = $shengyu >= $value["order_total_price"] ? $value["order_total_price"]:$shengyu;
            if($shop_money > 0){
                $shengyu -= $shop_money;
                $upShopSql = "update `ysmz_shop` set `shop_money`=`shop_money` + $shop_money,`frozen_money`=`frozen_money` + $shop_money,`update_time` = '$datetime' where `shop_id`=$value[shop_id] and `shop_money` = $shopInfo[shop_money]";
                $addShopLogSql = "insert into `ysmz_shop_account_log`(shop_id,shop_money,type,remarks,new_shop_money,data_id) values ($value[shop_id],$shop_money,'$type','$remarks',$shop_money+$shopInfo[shop_money],'$data_id')";
                if (!$db->save($upShopSql)) Common::exception("店铺余额更新失败");
                if (!$db->save($addShopLogSql)) Common::exception("店铺流水更新失败");
            }
            $shopFee_money =0;
            if($value["shipping_fee"] > 0){
                $shopFee_money = $shengyu >= $value["shipping_fee"] ? $value["shipping_fee"]:$shengyu;
                $shengyu -= $shopFee_money;
                $type = 5;
                $remarks = "商品运费";
                $datetime = date('Y-m-d H:i:s', time()+1);
                $upShopFeeSql = "update `ysmz_shop` set `shop_money`=`shop_money` + $shopFee_money,`frozen_money`=`frozen_money` + $shopFee_money,`update_time` = '$datetime' where `shop_id`=$value[shop_id] and `shop_money` = $shopInfo[shop_money] + $shop_money";
                $addShopFeeSql = "insert into `ysmz_shop_account_log`(shop_id,shop_money,type,remarks,new_shop_money,data_id) values ($value[shop_id],$shopFee_money,'$type','$remarks',$shop_money+$shopFee_money+$shopInfo[shop_money],'$data_id')";
                if (!$db->save($upShopFeeSql)) Common::exception("店铺运费余额更新失败");
                if (!$db->save($addShopFeeSql)) Common::exception("店铺运费更新失败");
            }
            $orderChild_pay_price = $shop_money + $shopFee_money;
            if($payment_type == 2){//微信支付
                $order_cloud_price = 0;
                $order_wechat_price = $orderChild_pay_price;
            }else{
                $order_cloud_price = $orderChild_pay_price;
                $order_wechat_price = 0;
            }
            $orderChildJoin = $orderJoin;
            /*if($value["order_type"] != 1){//虚拟商品支付成功后
                $order_state = 2;// 已发货
                $shipping_status = 1;// 已发货
                $orderChildJoin = $orderJoin.",shipping_time = '$datetime',shipping_status = $shipping_status,received_time = '$datetime'";
            }*/
            $order_number = $value["order_number"];
            $sku_id = $value["sku_id"];
            $upOrderSql = "update `ysmz_shop_goods_order` set `order_pay_price`=$orderChild_pay_price,`order_cloud_price`=$order_cloud_price,`order_wechat_price`=$order_wechat_price,`order_coupon_price` = $order_coupon_price,`payment_type` = '$payment_type',`pay_status` = $pay_status,`order_state` = $order_state $orderChildJoin where `order_id`=$value[order_id] and `user_id` = $user_id";
            $upSkuSql = "update `ysmz_shop_goods_sku` as gos,ysmz_shop_goods as g set g.sales_volume=g.sales_volume+$order_number,gos.sku_stock=gos.sku_stock-$order_number where gos.sku_id=$sku_id and gos.goods_id=g.goods_id";
            if (!$db->save($upOrderSql)) Common::exception("订单状态更新失败");
            if (!$db->save($upSkuSql)) Common::exception("库存更新失败");
        }
    }else{
        $queryOrder = $db->find("select `order_id`,`order_no`,`order_number`,`order_type`,`sku_id`,`shop_id`,`order_total_price`,`shipping_fee`,`order_fees`,`order_coupon_price`,`order_discount_price` from `ysmz_shop_goods_order` where `order_id` = $order_id FOR UPDATE");
        $type = 2;
        $remarks = "商品出售";
        $data_id = $queryOrder["order_no"];
        $shopInfo = $db->find("select `shop_id`,`status`,`shop_money`,`frozen_money` from `ysmz_shop` where `shop_id`=$queryOrder[shop_id]");
        $shop_money = $shengyu >= $queryOrder["order_total_price"] ? $queryOrder["order_total_price"]:$shengyu;
        $shengyu -= $shop_money;
        if($shop_money > 0){
            $upShopSql = "update `ysmz_shop` set `shop_money`=`shop_money` + $shop_money,`frozen_money`=`frozen_money` + $shop_money,`update_time` = '$datetime' where `shop_id`=$queryOrder[shop_id] and `shop_money` = $shopInfo[shop_money]";
            $addShopLogSql = "insert into `ysmz_shop_account_log`(shop_id,shop_money,type,remarks,new_shop_money,data_id) values ($queryOrder[shop_id],$shop_money,'$type','$remarks',$shop_money+$shopInfo[shop_money],'$data_id')";
            if (!$db->save($upShopSql)) Common::exception("店铺余额更新失败");
            if (!$db->save($addShopLogSql)) Common::exception("店铺流水更新失败");
        }
        if($queryOrder["shipping_fee"] > 0){
            $shopFee_money = $shengyu >= $queryOrder["shipping_fee"] ? $queryOrder["shipping_fee"]:$shengyu;
            $type = 5;
            $remarks = "商品运费";
            $datetime = date('Y-m-d H:i:s', time()+1);
            $upShopFeeSql = "update `ysmz_shop` set `shop_money`=`shop_money` + $shopFee_money,`frozen_money`=`frozen_money` + $shopFee_money,`update_time` = '$datetime' where `shop_id`=$queryOrder[shop_id] and `shop_money` = $shopInfo[shop_money] + $shop_money";
            $addShopFeeSql = "insert into `ysmz_shop_account_log`(shop_id,shop_money,type,remarks,new_shop_money,data_id) values ($queryOrder[shop_id],$shopFee_money,'$type','$remarks',$shop_money+$shopFee_money+$shopInfo[shop_money],'$data_id')";
            if (!$db->save($upShopFeeSql)) Common::exception("店铺运费余额更新失败");
            if (!$db->save($addShopFeeSql)) Common::exception("店铺运费更新失败");
        }
        $order_number = $queryOrder["order_number"];
        $sku_id = $queryOrder["sku_id"];
        if($order_number > 0){
            $upSkuSql = "update `ysmz_shop_goods_sku` as gos,ysmz_shop_goods as g set g.sales_volume=g.sales_volume+$order_number,gos.sku_stock=gos.sku_stock-$order_number where gos.sku_id=$sku_id and gos.goods_id=g.goods_id";
            if (!$db->save($upSkuSql)) Common::exception("主单库存更新失败");
        }
    }
    if($payment_type == 2){//微信支付
        $order_cloud_price = 0;
        $order_wechat_price = $order_pay_price;
    }else{
        $order_cloud_price = $order_pay_price;
        $order_wechat_price = 0;
    }
    /*if($data["order_type"] != 1){//虚拟商品支付成功后
        $order_state = 2;// 已发货
        $shipping_status = 1;// 已发货
        $orderJoin .= ",shipping_time = '$datetime',shipping_status = $shipping_status,received_time = '$datetime'";
    }*/
    $upOrderSql = "update `ysmz_shop_goods_order` set `order_pay_price`=$order_pay_price,`order_cloud_price`=$order_cloud_price,`order_wechat_price`=$order_wechat_price,`order_coupon_price` = $order_coupon_price,`payment_type` = '$payment_type',`pay_status` = $pay_status,`order_state` = $order_state,pay_time = '$datetime' $orderJoin where `order_id`=$order_id and `user_id` = $user_id";
    if (!$db->save($upOrderSql)) Common::exception("总订单更新失败");
}
function wechatPay($data)
{
    $db = new Db("host");
    $user_id = $data["user_id"];
    $coupon_id = $data["coupon_id"];
    $order_coupon_price = $data["order_coupon_price"];
    $order_id = $data["order_id"];
    $openid = $data["openid"];
    $payment_type = $data["payment_type"];
    $pay_no = Utils::createOrderNo("wx");
    $payConfig = Common::config('Pay');
    $db->startTrans();
    try {
        // 发起支付请求
        $resp = getInstance()
            ->chain('v3/pay/transactions/jsapi')
            ->post(['json' => [
                'mchid' => $payConfig['wechat']['mchid'],
                'description' => $data['goods_name'],
                'out_trade_no' => $pay_no,
                'notify_url' => "https://ysmz.scmzhc.com".$payConfig['wechat']['notify_url'],
                'appid' => $payConfig['wechat']['appid'],
                'amount' => [
                    'total' => round($data["order_pay_price"] * 100,2), // 单位: 分 $data["order_pay_price"]
                    'currency' => 'CNY'
                ],
                'payer' => [
                    'openid' => $openid
                ]
            ],'headers' => [
                'Wechatpay-Serial' => $payConfig['wechat']['wechatPayPublicKeyId'],
            ]]);
        // 处理响应
        $result_code = $resp->getStatusCode();
        if ($result_code == 200) {
            $result_data = json_decode($resp->getBody(), true);
            $arouse_data = [
                'appId' => $payConfig['wechat']['appid'],
                'nonceStr' => MD5($pay_no),
                'package' => "prepay_id=$result_data[prepay_id]",
                'timeStamp' => ''.Formatter::timestamp()
            ];
            $signString = $arouse_data['appId'] . "\n" .
                $arouse_data['timeStamp'] . "\n" .
                $arouse_data['nonceStr'] . "\n" .
                $arouse_data['package'] . "\n" ;
            $arouse_data['paySign'] = Rsa::sign($signString,
                Rsa::from($payConfig['wechat']['merchantPrivateKeyFilePath'], Rsa::KEY_TYPE_PRIVATE)
            );
            $arouse_data['signType'] = 'RSA';
            $setJoin = "";
            if(!empty($coupon_id)){
                $setJoin = " ,`coupon_id`=$coupon_id";
            }
            if(!empty($order_coupon_price)){
                $setJoin = " ,`$order_coupon_price`=$order_coupon_price";
            }
            if(!empty($payment_type)){
                $setJoin = " ,`payment_type`=$payment_type";
            }
            $upOrderSql = "update `ysmz_shop_goods_order` set `pay_no`='$pay_no',`openid` = '$openid' $setJoin where `order_id`=$order_id and `user_id` = $user_id";
            if(!$db->save($upOrderSql)) Result::error("支付单号更新失败");
            $db->commit();
            Result::success($arouse_data);
        }
    } catch (Exception $e) {
        // 处理异常
        Result::error("微信支付请求失败: " . $e->getMessage());
    }
}
/**
 * 微信支付请求配置 TODO
 * @return \WeChatPay\BuilderChainable
 */
function getInstance()
{
    $config = Common::config('Pay');
    // 商户号
    $merchantId = $config['wechat']['mchid'];

    // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
    $merchantPrivateKeyFilePath = $config['wechat']['merchantPrivateKeyFilePath'];
    $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);

    // 「商户API证书」的「证书序列号」
    $merchantCertificateSerial = $config['wechat']['merchantCertificateSerial'];

    //从本地文件中加载「微信支付公钥」，用来验证微信支付应答的签名
    $platformPublicKeyFilePath    = $config['wechat']['platformCertificateFilePath'];
    $twoPlatformPublicKeyInstance = Rsa::from($platformPublicKeyFilePath, Rsa::KEY_TYPE_PUBLIC);

// 「微信支付公钥」的「微信支付公钥ID」
// 需要在 商户平台 -> 账户中心 -> API安全 查询
    $platformPublicKeyId = $config['wechat']['wechatPayPublicKeyId'];
    // 构造一个 APIv3 客户端实例
    $instance = Builder::factory([
        'mchid' => $merchantId,
        'serial' => $merchantCertificateSerial,
        'privateKey' => $merchantPrivateKeyInstance,
        'certs' => [
            $platformPublicKeyId => $twoPlatformPublicKeyInstance,
        ],
    ]);
    return $instance;
}
/**
 * 用户充值
 */
function recharge($data)
{
    $user_id = Common::getUser_id($data);
    $amount = $data['amount'];
    $type = $data['type'];
    if(empty($type))$type=1;
    if($amount <=0 || $amount > 1000){
        Result::error("充值金额范围0.01-1000");
    }
    if(!in_array($type,[1,2,3])){
        Result::error("充值类型错误");
    }
    $db = new Db("host");
    $userInfo = $db->find("select `user_id`,`openid` from `user_info` where `user_id`=$user_id");
    if(empty($userInfo)){
        Result::error("用户信息错误，请退出后重新登录");
    }
    $openid = $userInfo['openid'];
    $pay_no = Utils::createOrderNo("cz");
    $payConfig = Common::config('Pay');
    $db->startTrans();
    try {
        // 发起支付请求
        $resp = getInstance()
            ->chain('v3/pay/transactions/jsapi')
            ->post(['json' => [
                'mchid' => $payConfig['wechat']['mchid'],
                'description' => "云上绵州线上支付",
                'out_trade_no' => $pay_no,
                'notify_url' => "https://ysmz.scmzhc.com/index.php/Callback/rechargePayCallback",
                'appid' => $payConfig['wechat']['appid'],
                'amount' => [
                    'total' => round($amount * 100,2), // 单位: 分 $data["order_pay_price"]
                    'currency' => 'CNY'
                ],
                'payer' => [
                    'openid' => $openid
                ]
            ],'headers' => [
                'Wechatpay-Serial' => $payConfig['wechat']['wechatPayPublicKeyId'],
            ]]);
        // 处理响应
        $result_code = $resp->getStatusCode();
        if ($result_code == 200) {
            $result_data = json_decode($resp->getBody(), true);
            $arouse_data = [
                'appId' => $payConfig['wechat']['appid'],
                'nonceStr' => MD5($pay_no),
                'package' => "prepay_id=$result_data[prepay_id]",
                'timeStamp' => ''.Formatter::timestamp()
            ];
            $signString = $arouse_data['appId'] . "\n" .
                $arouse_data['timeStamp'] . "\n" .
                $arouse_data['nonceStr'] . "\n" .
                $arouse_data['package'] . "\n" ;
            $arouse_data['paySign'] = Rsa::sign($signString,
                Rsa::from($payConfig['wechat']['merchantPrivateKeyFilePath'], Rsa::KEY_TYPE_PRIVATE)
            );
            $arouse_data['signType'] = 'RSA';
            $rechargeSql = "INSERT INTO `user_recharge_order` ( `user_id`,`pay_no`,`amount`,`type`) VALUES ($user_id,'$pay_no',$amount,$type)";
            if(!$db->save($rechargeSql)) Result::error("充值订单加载失败");
            $db->commit();
            Result::success($arouse_data);
        }
    } catch (Exception $e) {
        // 处理异常
        Result::error("微信支付请求失败: " . $e->getMessage());
    }
}
/**
 * 用户扫码付
 */
function scanPay($data)
{
    $user_id = Common::getUser_id($data);
    $amount = $data['amount'];
    $sid = $data['sid'];
    $type = $data['type'];//1线下商家 2 线上商家
    $payType = $data['payType'];//支付方式//cloudPay//wechatPay
    $trade_password = $data['trade_password'];//支付密码
    if($amount <=0 || $amount > 10000){
        Result::error("支付金额范围0.01-10000");
    }
    $db = new Db("host");
    $userInfo  = $db->find("select ui.`user_id`,ui.`openid`,uei.`trade_password` from `user_info` as ui inner join `user_extra_info` as uei on ui.user_id = uei.user_id where ui.`user_id`=$user_id");
    if(empty($userInfo)){
        Result::error("用户信息错误，请退出后重新登录");
    }
    if($payType != "wechatPay" && !empty($trade_password)){
        if(empty($userInfo["trade_password"])){
            Result::error("您还未设置支付密码，请先设置！");
        }
        $userInfo['trade_password'] = Common::passwordTh($userInfo['trade_password']);
        $generalVerify = Common::config('config')['generalVerify']['password'];
        if ($trade_password != $generalVerify && !password_verify($trade_password, $userInfo['trade_password'])){
            Result::error("支付密码错误");
        }
    }
    switch ($type) {
        case 1:
            $offlineInfo = $db->find("select `merchant_id`,`state`,`is_delete`,`section_id` from `ysmz_merchant_offline` where `merchant_id`=$sid");
            if(empty($offlineInfo)){
                Result::error("商家不存在");
            }
            if($offlineInfo["state"] != 1 || $offlineInfo["is_delete"] != 0 ){
                Result::error("商家未审核或已删除");
            }
            if(!isMerchantPay($offlineInfo["section_id"],$payType)){
                Result::error("商家不支持当前支付方式");
            }
            break;
        case 2:
            Result::error("暂未开通线上店铺扫码");
            $shopInfo = $db->find("select `shop_id`,`status`,`section_id` from `ysmz_shop` where `shop_id`=$sid");
            if(empty($shopInfo)){
                Result::error("店铺不存在");
            }
            if($shopInfo["status"] != 1){
                Result::error("店铺已暂停运营");
            }
            if(!isMerchantPay($shopInfo["section_id"],$payType)){
                Result::error("店铺不支持当前支付方式");
            }
            break;
        default:Result::error("未知商家");break;
    }
    $data["user_id"] = $user_id;
    switch ($payType) {
        case 'cloudPay'://余额支付
            $data["payment_type"] = 1;
            scanCloudPay($data);
            break;
        case 'wechatPay'://微信支付
            $data["openid"] = $userInfo["openid"];
            scanWechatPay($data);
            break;
        case 'birthPay'://生日豆支付
            $data["payment_type"] = 4;
            scanCloudPay($data);
            break;
        case 'assistPay'://帮扶豆支付
            $data["payment_type"] = 5;
            scanCloudPay($data);
            break;
        default:Result::error("请选择支付方式");
    }
    Result::success();
}
function scanWechatPay($data)
{
    $db = new Db("host");
    $user_id = $data['user_id'];
    $openid = $data['openid'];
    $amount = $data['amount'];
    $sid = $data['sid'];
    $type = $data['type'];
    $pay_no = Utils::createOrderNo("scan");
    $payConfig = Common::config('Pay');
    $db->startTrans();
    try {
        // 发起支付请求
        $resp = getInstance()
            ->chain('v3/pay/transactions/jsapi')
            ->post(['json' => [
                'mchid' => $payConfig['wechat']['mchid'],
                'description' => "云上绵州线下支付",
                'out_trade_no' => $pay_no,
                'notify_url' => "https://ysmz.scmzhc.com/index.php/Callback/scanPayCallback",
                'appid' => $payConfig['wechat']['appid'],
                'amount' => [
                    'total' => round($amount * 100 , 2), // 单位: 分 $data["order_pay_price"]
                    'currency' => 'CNY'
                ],
                'payer' => [
                    'openid' => $openid
                ]
            ],'headers' => [
                'Wechatpay-Serial' => $payConfig['wechat']['wechatPayPublicKeyId'],
            ]]);
        // 处理响应
        $result_code = $resp->getStatusCode();
        if ($result_code == 200) {
            $result_data = json_decode($resp->getBody(), true);
            $arouse_data = [
                'appId' => $payConfig['wechat']['appid'],
                'nonceStr' => MD5($pay_no),
                'package' => "prepay_id=$result_data[prepay_id]",
                'timeStamp' => ''.Formatter::timestamp()
            ];
            $signString = $arouse_data['appId'] . "\n" .
                $arouse_data['timeStamp'] . "\n" .
                $arouse_data['nonceStr'] . "\n" .
                $arouse_data['package'] . "\n" ;
            $arouse_data['paySign'] = Rsa::sign($signString,
                Rsa::from($payConfig['wechat']['merchantPrivateKeyFilePath'], Rsa::KEY_TYPE_PRIVATE)
            );
            $arouse_data['signType'] = 'RSA';
            $rechargeSql = "INSERT INTO `user_scan_order` ( `user_id`,`sid`,`pay_no`,`type`) VALUES ($user_id,$sid,'$pay_no',$type)";
            if(!$db->save($rechargeSql)) Result::error("扫码付订单加载失败");
            $db->commit();
            Result::success($arouse_data);
        }
    } catch (Exception $e) {
        // 处理异常
        Result::error("微信支付请求失败: " . $e->getMessage());
    }
}
function scanCloudPay($data)
{
    $db = new Db("host");
    $user_id = $data["user_id"];
    $type = $data["type"];
    $sid = $data["sid"];
    $order_total_price = $data["order_pay_price"] = $data["amount"];

    $userInfo = $db->find("select `cloud_bean`,`birth_bean`,`assist_bean` from `user_info` where `user_id`=$user_id");
    switch ($data["payment_type"]) {
        case 1:
            $data["cloud_bean"] = $userInfo["cloud_bean"];
            if($userInfo["cloud_bean"] < 0){
                Result::error("用户余额异常，请联系管理员");
            }
            if($userInfo["cloud_bean"] < $order_total_price){
                Result::error("用户余额不足");
            }
            $data["data_src"] = 1;
            break;
        case 4:
            $data["birth_bean"] = $userInfo["birth_bean"];
            if($userInfo["birth_bean"] < 0){
                Result::error("用户余额异常，请联系管理员");
            }
            if($userInfo["birth_bean"] < $order_total_price){
                Result::error("用户生日豆不足");
            }
            $data["data_src"] = 3;
            break;
        case 5:
            $data["assist_bean"] = $userInfo["assist_bean"];
            if($userInfo["assist_bean"] < 0){
                Result::error("用户余额异常，请联系管理员");
            }
            if($userInfo["assist_bean"] < $order_total_price){
                Result::error("用户帮扶豆不足");
            }
            $data["data_src"] = 4;
            break;
    }
    $queryMerchantName = queryMerchantName($sid,$type);
    $data["order_total_price"] = $order_total_price;
    $data["data_remarks"] = "扫码付-".$queryMerchantName;
    $data["data_id"] = $data["pay_no"] = Utils::createOrderNo("scan");
    $datetime = date("Y-m-d H:i:s",time());
    $db->startTrans();
    try {
        userOperationCloud($db,$data);//更新用户余额
        if($type == 1){//线下商家更新余额和明细
            offlineSettlement($db,$data);
        }
        if($type == 2){//线上商家更新余额和明细
            shopSettlement($db,$data);
        }
        $rechargeSql = "INSERT INTO `user_scan_order` ( `user_id`,`sid`,`pay_no`,`amount`,`type`,`status`,`payment_type`,`paid_time`) VALUES ($user_id,$sid,'$data[pay_no]',$order_total_price,$type,1,$data[payment_type],'$datetime')";
        if(!$db->save($rechargeSql)) Result::error("扫码付订单加载失败");
        $db->commit();
    } catch (\Exception $e) {
        $db->rollback();
        Result::error($e->getMessage());
    }
    $messagesData["type"] = $type;
    $messagesData["sid"] = $sid;
    $messagesData["msg_type"] = 1;
    $messagesData["msg"] = $data["data_remarks"];
    $messagesData["trade_no"] = $data["pay_no"];
    pushCrmMessages($messagesData);
    Result::success("ok");
}
function offlineSettlement($db,$data)
{
    $remarks = "扫码付";
    $data_id = $data["pay_no"];
    $shop_id = $data["sid"];
    $shop_money = $data["order_pay_price"];
    $datetime = date("Y-m-d H:i:s",time());
    $shopInfo = $db->find("select `merchant_id`,`cloud_bean` from `ysmz_merchant_offline` where `merchant_id`=$shop_id");
    $upShopSql = "update `ysmz_merchant_offline` set `cloud_bean`=`cloud_bean` + $shop_money,`total_bean`=`total_bean` + $shop_money,`update_time` = '$datetime' where `merchant_id`=$shop_id and `cloud_bean` = $shopInfo[cloud_bean]";
    $addShopLogSql = "insert into `ysmz_merchant_offline_funds`(merchant_id,order_number,direction,type,amount,balance) values ($shop_id,'$data_id','$remarks',1,$shop_money,$shop_money+$shopInfo[cloud_bean])";
    if (!$db->save($upShopSql)) Common::exception("商家余额更新失败");
    if (!$db->save($addShopLogSql)) Common::exception("商家流水更新失败");
}
function shopSettlement($db,$data)
{
    $type = 3;
    $remarks = "扫码付";
    $data_id = $data["pay_no"];
    $shop_id = $data["sid"];
    $shop_money = $data["order_pay_price"];
    $datetime = date("Y-m-d H:i:s",time());
    $shopInfo = $db->find("select `shop_id`,`status`,`shop_money`,`frozen_money` from `ysmz_shop` where `shop_id`=$shop_id");
    $upShopSql = "update `ysmz_shop` set `shop_money`=`shop_money` + $shop_money,`frozen_money`=`frozen_money` + $shop_money,`update_time` = '$datetime' where `shop_id`=$shop_id and `shop_money` = $shopInfo[shop_money]";
    $addShopLogSql = "insert into `ysmz_shop_account_log`(shop_id,shop_money,type,remarks,new_shop_money,data_id) values ($shop_id,$shop_money,'$type','$remarks',$shop_money+$shopInfo[shop_money],'$data_id')";
    if (!$db->save($upShopSql)) Common::exception("店铺余额更新失败");
    if (!$db->save($addShopLogSql)) Common::exception("店铺流水更新失败");
}
function queryMerchantName($sid,$type)
{
    $db = new Db();
    switch ($type) {
        case 1:
            $offlineInfo = $db->find("select `merchant_name` from `ysmz_merchant_offline` where `merchant_id`=$sid");
            $name = $offlineInfo["merchant_name"];
            break;
        case 2:
            $shopInfo = $db->find("select `shop_id`,`status`,`shop_logo`,`shop_title` from `ysmz_shop` where `shop_id`=$sid");
            $name = $shopInfo["shop_title"];
            break;
    }
    return $name ?? "未知商家";
}

function isMerchantPay($section_id,$paymentMethod)
{
    $db = new Db();
    $sql="select `id`,`value` from `mall_config` where `business` = 'pay' and `status` =0 and `type` in(0,$section_id)";
    $query = $db->query($sql);
    if(empty($query)){
        return false;
    }
    foreach ($query as $k=>$v){
        if($v["value"] == $paymentMethod){
            return true;
        }
    }
    return false;
}
/**
 * 推送后台消息
 * */
function pushCrmMessages($data)
{
    $sid = $data['sid'];
    $type = $data['type'];
    $msg = $data['msg'];
    $msg_type = $data['msg_type'];
    $trade_no = $data['trade_no'];
    //sign = （$sid + $type + 'jYylSFE585fEE84KLIUYhgsdf@'） 两次MD5
    $sign = md5(md5($sid.$type."jYylSFE585fEE84KLIUYhgsdf@"));
    $bodys = "?sid=$sid&type=$type&msg=$msg&msg_type=$msg_type&trade_no=$trade_no&sign=$sign";
    $url = "http://crm.scmzhc.com/gCJqIxYPfe.php/Orderpush/index".$bodys;
    $client = new Client();
    $response = $client->get($url);
    $response->getStatusCode();
}
/**
 * 推送发货信息到微信API(虚拟商品)
 * */
function uploadShippingInfo($data)
{
    $payConfig = Common::config('Pay');
    $getAccessToken = getAccessToken();
    $url = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=".$getAccessToken;
    $api_data = [
        'order_key' => [
            'order_number_type' => 1,
            'mchid' => $payConfig["wechat"]["mchid"],
            'out_trade_no' => $data['out_trade_no']
        ],
        'logistics_type' => $data["logistics_type"],//1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品，虚拟商品，例如话费充值，点卡等，无实体配送形式 4、用户自提
        'delivery_mode' => 1,
        'shipping_list' => [
            [
                'item_desc' => $data["item_desc"]//云豆充值//线下消费
            ]
        ],
        'upload_time' => date('c'), // ISO 8601格式
        'payer' => [
            'openid' => $data["openid"]
        ]
    ];
    $client = new Client();
    $api_data = json_encode($api_data, JSON_UNESCAPED_UNICODE);
    $response = $client->post($url,['body' => $api_data]);
    return json_decode($response->getBody(), true);
}
function getAccessToken()
{
    $payConfig = Common::config('Pay');
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$payConfig['wechat']['appid']}&secret={$payConfig['wechat']['app_secret']}";
    $client = new Client();
    $response = $client->post($url);
    $json_decode = json_decode($response->getBody(), true);
    return $json_decode["access_token"];
}